package de.lulusoft.anothertorrent.gui.views;


import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.part.ViewPart;
import org.eclipse.ui.progress.UIJob;

import de.lulusoft.anothertorrent.core.rtorrent.Torrent;
import de.lulusoft.anothertorrent.core.rtorrent.View;
import de.lulusoft.anothertorrent.gui.AnotherTorrentGui;
import de.lulusoft.anothertorrent.gui.commands.ChangeTorrentPriorityCommand;
import de.lulusoft.anothertorrent.gui.preferences.PreferenceConstants;
import de.lulusoft.anothertorrent.gui.views.Providers.TableColumnSorter;
import de.lulusoft.anothertorrent.gui.views.Providers.TorrentDetailsViewInput;
import de.lulusoft.anothertorrent.gui.views.Providers.TorrentListViewContentProvider;
import de.lulusoft.anothertorrent.gui.views.Providers.TorrentListViewInput;
import de.lulusoft.anothertorrent.gui.views.Providers.TorrentListViewLabelProvider;
import de.lulusoft.anothertorrent.gui.views.Providers.TorrentListViewPriorityEditingSupport;

public class TorrentListView extends ViewPart{
	
	public static final String ID = "de.lulusoft.anothertorrent.gui.views.TorrentListView";

//	private static TorrentListView me = null;
	private static final String[] properties = {"Name", "Status", "Done", 
		"Remain", "Size", "Down", "Up", "Seeded",
		"Ratio", "Peers", "Priority"};
	
	private TableViewer viewer = null;
	private Job timer = null;
	private long timerInterval = 1000;
	private View m_view = null;
	private TorrentListViewInput m_input = null;
	

	@Override
	public void dispose() {
		if (timer != null)
		{
			timer.cancel();
		}
		super.dispose();
	}

	public TorrentListView() {
		
	}
	
	public void setInput(Object input)
	{
		if (input instanceof TorrentListViewInput)
		{
			m_input = (TorrentListViewInput)input;
			// Stop timer
			timer.cancel();
			// Set view name
			setPartName("View: " + m_input.getServer().getName() + "." + m_input.getViewName());
			// fetch view
			m_view = m_input.getServer().getRTorrentManager().getView(m_input.getViewName());
			viewer.setInput(m_view);
			// auto fit columns
			for (TableColumn tc : viewer.getTable().getColumns())
				tc.pack();
			// add timer
			 timer.schedule(timerInterval);
		}
	}

	@Override
	public void createPartControl(Composite parent) {

		parent.setLayout(new GridLayout(1,true));
		GridData gd = new GridData(SWT.FILL, SWT.FILL, true, false);
		Composite toolbar = new Composite(parent, SWT.FILL);
		toolbar.setLayoutData(gd);
		toolbar.setLayout(new RowLayout());
		
		Button cmdDelete = new Button(toolbar, SWT.PUSH);
		cmdDelete.setImage(AnotherTorrentGui.createImage("delete.png"));
		cmdDelete.setToolTipText("Delete Torrent(s) (not the contents on disk)");
		cmdDelete.addSelectionListener(new SelectionListener() {
			@SuppressWarnings("unchecked")
			@Override
			public void widgetSelected(SelectionEvent e) {
				IStructuredSelection sel = (IStructuredSelection)viewer.getSelection();	
				if(!sel.isEmpty())
				{
					Iterator<Torrent> it = sel.iterator();
					while (it.hasNext())
					{
						Torrent t = it.next();
						t.getServer().getRTorrentManager().torrentErase(t.getHash());
					}
				}	
			}
			@Override
			public void widgetDefaultSelected(SelectionEvent e) {}
		});
		
		Button cmdStop = new Button(toolbar, SWT.PUSH);
		cmdStop.setImage(AnotherTorrentGui.createImage("stop.png"));
		cmdStop.setToolTipText("Stop Torrent(s)");
		cmdStop.addSelectionListener(new SelectionListener() {
			@SuppressWarnings("unchecked")
			@Override
			public void widgetSelected(SelectionEvent e) {
				IStructuredSelection sel = (IStructuredSelection)viewer.getSelection();	
				if(!sel.isEmpty())
				{
					Iterator<Torrent> it = sel.iterator();
					while (it.hasNext())
					{
						Torrent t = it.next();
						t.getServer().getRTorrentManager().torrentStop(t.getHash());
						t.setState(0L);
					}
				}	
			}
			@Override
			public void widgetDefaultSelected(SelectionEvent e) {}
		});
				
		Button cmdPlay = new Button(toolbar, SWT.PUSH);
		cmdPlay.setImage(AnotherTorrentGui.createImage("control_play_blue.png"));
		cmdPlay.setToolTipText("Start Torrent(s)");
		cmdPlay.addSelectionListener(new SelectionListener() {
			@SuppressWarnings("unchecked")
			@Override
			public void widgetSelected(SelectionEvent e) {
				IStructuredSelection sel = (IStructuredSelection)viewer.getSelection();	
				if(!sel.isEmpty())
				{
					Iterator<Torrent> it = sel.iterator();
					while (it.hasNext())
					{
						Torrent t = it.next();
						t.getServer().getRTorrentManager().torrentStart(t.getHash());
						t.setState(1L);
					}
				}		
			}
			@Override
			public void widgetDefaultSelected(SelectionEvent e) {}
		});
		
		final Menu mnuSetPrio = new Menu(toolbar.getParent().getShell(), SWT.POP_UP);
		MenuItem miOff = new MenuItem(mnuSetPrio, SWT.NONE);
		miOff.setText("Off");
		miOff.addSelectionListener(new SelectionListener() {
			@SuppressWarnings("unchecked")
			@Override
			public void widgetSelected(SelectionEvent e) {
				IStructuredSelection sel = (IStructuredSelection)viewer.getSelection();	
				if(!sel.isEmpty())
				{
					Iterator<Torrent> it = sel.iterator();
					while (it.hasNext())
					{
						Torrent t = it.next();
						ChangeTorrentPriorityCommand cmd = new ChangeTorrentPriorityCommand();
						Map<String, String> params = new HashMap<String, String>();
						params.put(ChangeTorrentPriorityCommand.P_PRIORITY, "0");
						ExecutionEvent event = new ExecutionEvent(null, params, t, null);
						try {
							cmd.execute(event);
						} catch (ExecutionException e1) {
							e1.printStackTrace();
						}
					}
				}	
			}
			@Override
			public void widgetDefaultSelected(SelectionEvent e) {}
		});
		MenuItem miLow = new MenuItem(mnuSetPrio, SWT.NONE);
		miLow.setText("Low");
		miLow.addSelectionListener(new SelectionListener() {
			@SuppressWarnings("unchecked")
			@Override
			public void widgetSelected(SelectionEvent e) {
				IStructuredSelection sel = (IStructuredSelection)viewer.getSelection();	
				if(!sel.isEmpty())
				{
					Iterator<Torrent> it = sel.iterator();
					while (it.hasNext())
					{
						Torrent t = it.next();
						ChangeTorrentPriorityCommand cmd = new ChangeTorrentPriorityCommand();
						Map<String, String> params = new HashMap<String, String>();
						params.put(ChangeTorrentPriorityCommand.P_PRIORITY, "1");
						ExecutionEvent event = new ExecutionEvent(null, params, t, null);
						try {
							cmd.execute(event);
						} catch (ExecutionException e1) {
							e1.printStackTrace();
						}
					}
				}	
			}
			@Override
			public void widgetDefaultSelected(SelectionEvent e) {}
		});
		MenuItem miNormal = new MenuItem(mnuSetPrio, SWT.NONE);
		miNormal.setText("Normal");
		miNormal.addSelectionListener(new SelectionListener() {
			@SuppressWarnings("unchecked")
			@Override
			public void widgetSelected(SelectionEvent e) {
				IStructuredSelection sel = (IStructuredSelection)viewer.getSelection();	
				if(!sel.isEmpty())
				{
					Iterator<Torrent> it = sel.iterator();
					while (it.hasNext())
					{
						Torrent t = it.next();
						ChangeTorrentPriorityCommand cmd = new ChangeTorrentPriorityCommand();
						Map<String, String> params = new HashMap<String, String>();
						params.put(ChangeTorrentPriorityCommand.P_PRIORITY, "2");
						ExecutionEvent event = new ExecutionEvent(null, params, t, null);
						try {
							cmd.execute(event);
						} catch (ExecutionException e1) {
							e1.printStackTrace();
						}
					}
				}	
			}
			@Override
			public void widgetDefaultSelected(SelectionEvent e) {}
		});
		MenuItem miHigh = new MenuItem(mnuSetPrio, SWT.NONE);
		miHigh.setText("High");
		miHigh.addSelectionListener(new SelectionListener() {
			@SuppressWarnings("unchecked")
			@Override
			public void widgetSelected(SelectionEvent e) {
				IStructuredSelection sel = (IStructuredSelection)viewer.getSelection();	
				if(!sel.isEmpty())
				{
					Iterator<Torrent> it = sel.iterator();
					while (it.hasNext())
					{
						Torrent t = it.next();
						ChangeTorrentPriorityCommand cmd = new ChangeTorrentPriorityCommand();
						Map<String, String> params = new HashMap<String, String>();
						params.put(ChangeTorrentPriorityCommand.P_PRIORITY, "3");
						ExecutionEvent event = new ExecutionEvent(null, params, t, null);
						try {
							cmd.execute(event);
						} catch (ExecutionException e1) {
							e1.printStackTrace();
						}
					}
				}	
			}
			@Override
			public void widgetDefaultSelected(SelectionEvent e) {}
		});
		
		final Button cmdSetPrio = new Button(toolbar, SWT.PUSH | SWT.DROP_DOWN);
		cmdSetPrio.setText("Set Priority");
		cmdSetPrio.addSelectionListener(new SelectionListener(){

			public void widgetDefaultSelected(SelectionEvent e) {}

			public void widgetSelected(SelectionEvent e) {
				if ( !mnuSetPrio.isVisible() ) {
					Rectangle bounds = cmdSetPrio.getBounds();
					Point menuLoc =
						cmdSetPrio.getParent().toDisplay(bounds.x, bounds.y + bounds.height);

					mnuSetPrio.setLocation(menuLoc.x, menuLoc.y);
					mnuSetPrio.setVisible(true);
				}
			}			
		});
			
		
		Composite viewerComp = new Composite(parent, SWT.FILL | SWT.BORDER);
		gd = new GridData(SWT.FILL, SWT.FILL, true, true);
		viewerComp.setLayoutData(gd);
		viewerComp.setLayout(new FillLayout());
		viewer = new TableViewer(viewerComp,  SWT.FULL_SELECTION | SWT.MULTI);
		viewer.setColumnProperties(properties);
		viewer.getTable().setHeaderVisible(true);
		viewer.getTable().setLinesVisible(true);
		
		// add columns
		int i = 0;
		for (final String prop : properties)
		{
			final int colIdx = i;
			TableViewerColumn column = new TableViewerColumn(viewer, SWT.NONE);
			column.getColumn().setText(prop);
			column.getColumn().setWidth(100);
			column.getColumn().setMoveable(true);
			
			if (prop.equals("Priority"))
			{
				column.setEditingSupport(new TorrentListViewPriorityEditingSupport(viewer));
			}

			// Add Sorters..
			TableColumnSorter cSorter = new TableColumnSorter(viewer, column.getColumn()) 
			{
			     protected int doCompare(Viewer v, Object e1, Object e2) 
			     {
			    	 Torrent t1 = (Torrent)e1;
			    	 Torrent t2 = (Torrent)e2;
			    	 if (prop.equals("Remain"))
			    	 {
			    		return t1.getRemainingBytes().compareTo(t2.getRemainingBytes()); 
			    	 }
			    	 else if (prop.equals("Size"))
			    	 {
			    		return t1.getSize_bytes().compareTo(t2.getSize_bytes()); 
			    	 }
			    	 else if (prop.equals("Down"))
			    	 {
			    		return t1.getDown_rate().compareTo(t2.getDown_rate()); 
			    	 }
			    	 else if (prop.equals("Up"))
			    	 {
			    		return t1.getUp_rate().compareTo(t2.getUp_rate()); 
			    	 }
			    	 else if (prop.equals("Seeded"))
			    	 {
			    		return t1.getUp_total().compareTo(t2.getUp_total()); 
			    	 }
			    	 else if (prop.equals("Done"))
			    	 {
			    		return t1.getDonePercent().compareTo(t2.getDonePercent()); 
			    	 }
			    	 else if (prop.equals("Priority"))
			    	 {
			    		return t1.getPriority().compareTo(t2.getPriority()); 
			    	 }
			    	 else
			    	 {
			             ITableLabelProvider lp = ((ITableLabelProvider) viewer
			            		 .getLabelProvider());
			             String s1 = lp.getColumnText(e1, colIdx);
			             String s2 = lp.getColumnText(e2, colIdx);
			             return s1.compareTo(s2);
			    	 }
			     }
			};

			cSorter.setSorter(cSorter, TableColumnSorter.ASC);
			i++;
		}
		
		viewer.setContentProvider(new TorrentListViewContentProvider());
		viewer.setLabelProvider(new TorrentListViewLabelProvider());
		
		viewer.addDoubleClickListener(new IDoubleClickListener() {
		
			@Override
			public void doubleClick(DoubleClickEvent event) {
				
				if (event.getSelection() instanceof IStructuredSelection)
				{
					IStructuredSelection s = (IStructuredSelection)event.getSelection();
					if (s.getFirstElement() instanceof Torrent)
					{
						Torrent t = (Torrent)s.getFirstElement();

						
						try 
						{
							TorrentDetailsView tv = (TorrentDetailsView)
								AnotherTorrentGui.getDefault()
								.getWorkbench().getActiveWorkbenchWindow()
								.getActivePage().showView(TorrentDetailsView.ID, 
										t.getName(), IWorkbenchPage.VIEW_ACTIVATE);
							tv.setInput(new TorrentDetailsViewInput(m_input.getServer(), t));
						} catch (Exception e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
						
					}
				}
		
			}
		});
		
		// create update timer
		timer = new Job("Updating Data for View...") {
			
			@Override
			protected IStatus run(IProgressMonitor monitor) {
				try
				{
					monitor.beginTask("Updating Data for View: " + m_input.getViewName() , IProgressMonitor.UNKNOWN);
					// Update Data
					m_input.getServer().getRTorrentManager().updateView(m_view);
					// Update Timer
					timerInterval = AnotherTorrentGui.getDefault()
						.getPreferenceStore().getInt(PreferenceConstants.P_UPDATE_INTERVAL_LIST_VIEW) * 1000;
					this.schedule(timerInterval);
					// Update UI
					UIJob ui = new UIJob(Display.getDefault(), "Updating View: " + m_input.getViewName()){

						@Override
						public IStatus runInUIThread(IProgressMonitor monitor) {
							try
							{
							monitor.beginTask("Updating View: " + m_input.getViewName() , IProgressMonitor.UNKNOWN);
							// Save current selection
							ISelection sel = viewer.getSelection();
							// Update View
							m_view.updateGUI();
							// Restore selection
							viewer.setSelection(sel, false);
							monitor.done();
							}
							catch (Exception e) {
								e.printStackTrace();
							}
							
							return null;
						}
						
					};
					ui.schedule();
					monitor.done();
				}
				catch (Exception e)
				{
					e.printStackTrace();
				}
				
				return null;
				
			}
		};
		timer.setUser(false);
		timerInterval = AnotherTorrentGui.getDefault()
			.getPreferenceStore().getInt(PreferenceConstants.P_UPDATE_INTERVAL_LIST_VIEW) * 1000;
	}

	@Override
	public void setFocus() {
		// TODO Auto-generated method stub

	}
	
	  public View getM_view() {
		return m_view;
	}

	

}
